<!DOCTYPE html><html><head><title>HTML5游戏V3版本接入文档</title><meta charset='utf-8'><link href='https://dn-maxiang.qbox.me/res-min/themes/marxico.css' rel='stylesheet'><style></style></head><body><div id='preview-contents' class='note-content'>
                        
                    

<div><div class="toc"><div class="toc">
<ul>
<li><ul>
<li><a href="#html5游戏v3版本接入文档">HTML5游戏V3版本接入文档</a><ul>
<li><ul>
<li><a href="#技术接入前置">技术接入前置</a></li>
<li><a href="#接入预览">接入预览</a></li>
<li><a href="#登录流程">登录流程</a><ul>
<li><a href="#登录时序图">登录时序图</a></li>
<li><a href="#游戏登录接口">游戏登录接口</a></li>
<li><a href="#用户退出接口">用户退出接口</a></li>
</ul>
</li>
<li><a href="#支付流程">支付流程</a><ul>
<li><a href="#支付时序图">支付时序图</a></li>
<li><a href="#支付面板接口">支付面板接口</a></li>
<li><a href="#发放游戏币接口">发放游戏币接口</a></li>
</ul>
</li>
<li><a href="#常见问题说明">常见问题说明</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>



<h2 id="html5游戏v3版本接入文档">HTML5游戏V3版本接入文档</h2>



<h4 id="技术接入前置">技术接入前置</h4>

<ul><li>需要<a href="http://www.4399api.com" target="_blank">原创平台</a>先注册：开发者和游戏</li>
<li>提供以下信息 <br>
<ul>
<li>游戏是横屏还是竖屏</li>
<li>游戏币名称</li>
<li>游戏币兑换比例和相关列表 <br>
<ul>
<li>比例：如10表示1人民币兑换10游戏币</li>
<li>列表：金额不可重复 <br>
1||1元 <br>
2||2元 <br>
5||5元 <br>
10||10元</li></ul></li>
<li>游戏的链接地址（游戏登录接口）<code>[需游戏根据本文档定义实现]</code></li>
<li>游戏币发放的回调地址<code>[需游戏根据本文档定义实现]</code></li></ul></li>
<li>我们根据以上信息，返回游戏gameId和callbackKey信息</li>
<li>测试地址：<a href="http://save.api.4399.com/h5/v3/h5-frame/index.html?gameId=$gameId" target="_blank">http://save.api.4399.com/h5/v3/h5-frame/index.html?gameId=$gameId</a></li>
</ul>

<hr>



<h4 id="接入预览">接入预览</h4>



<p><img longdesc="./1487323925051.png" alt="Alt text" title="" type="image/png" src="" class=""></p>

<ul><li>游戏需实现的接口 <br>
<ul>
<li>游戏登录接口<code>[server接口</code></li>
<li>游戏币发放接口<code>[server接口]</code></li></ul></li>
<li>平台提供的接口 <br>
<ul>
<li>用户退出接口<code>[client接口/js]</code></li>
<li>支付接口<code>[client接口/js]</code></li></ul></li>
</ul>

<hr>



<h4 id="登录流程">登录流程</h4>



<h5 id="登录时序图">登录时序图</h5>



<div class="sequence-diagram" rel="8bf9dde9239ad8034c41fa4dccc48f60"><span><img type="image/png" width="327" height="329" longdesc="__SVG__undefined" src="" style="margin-top:0;margin-bottom:0;"></span></div>

<ul><li>游戏在平台展现方式：平台入口地址，用iframe嵌套<code>[游戏登录接口|游戏]</code></li>
<li>用户打开平台入口地址，4399平台校验用户是否已登录 <br>
<ul>
<li>未登录，进登录页，用户输入用户名和密码，重新进游戏；</li>
<li>已登录，将用户通过sign授权给游戏；</li></ul></li>
<li>游戏根据<code>游戏登录接口</code>定义的输入参数，校验sign值； <br>
<ul>
<li>sign传递方式：GET方式，传递给游戏登录接口 <br>
<ul>
<li>sign正确，进入游戏；</li>
<li>sign不正确，调用<code>用户退出接口</code>，重新登录；</li></ul></li>
<li>登录接口由游戏服务器端处理，server to server的验证sign保证用户账号的安全</li>
<li>账号信息由游戏服务器端传递给游戏客户端，进入游戏</li></ul></li>
</ul>



<h5 id="游戏登录接口">游戏登录接口</h5>

<ul><li>提供方：<code>游戏</code></li>
<li>说明：平台用户登录时，授权用户登录游戏；</li>
<li>使用场景：平台用户登录后，直接将参数以get方式http跳转到该接口</li>
<li>接口： <code>游戏提供</code></li>
<li>测试接口：<code>游戏提供</code></li>
<li>调用方式:GET</li>
</ul>



<pre class="prettyprint hljs-dark"><code class="hljs xquery">输入:<br>   <span class="hljs-string">'gameId'</span> =&gt; <span class="hljs-number">100042396</span>,   /// 该游戏在原创平台的ID，在技术接入前置会提供<br>   <span class="hljs-string">'userId'</span> =&gt; <span class="hljs-number">594437088</span>,   /// 用户在<span class="hljs-number">4399</span>平台的ID<br>   <span class="hljs-string">'userName'</span> =&gt; <span class="hljs-string">'high咖c'</span>, /// 用户在<span class="hljs-number">4399</span>的昵称或用户名<br>   <span class="hljs-string">'time'</span> =&gt; <span class="hljs-number">1447228562</span>,    /// 时间戳，精确到秒，游戏需要校验在一定时间内该链接请求可用，超过时间该链接不可用；一般为<span class="hljs-number">2</span>分钟，可自定义<br>   <span class="hljs-string">'sign'</span> =&gt; <span class="hljs-string">'0c315c264f32be0ff0f152ee0b39cb8e'</span>, /// md5(sprintf(<span class="hljs-string">"gameId=%stime=%suserId=%suserName=%s%s"</span>, <span class="hljs-variable">$gameId</span>, <span class="hljs-variable">$time</span>, <span class="hljs-variable">$userId</span>, <span class="hljs-variable">$userName</span>, <span class="hljs-variable">$callbackKey</span>));<br></code></pre>



<pre class="prettyprint hljs-dark"><code class="hljs crystal">输出:<br>    <span class="hljs-regexp">//</span><span class="hljs-regexp">/ 1.sign校验成功，用户进入游戏；<br>    /</span><span class="hljs-regexp">//</span> <span class="hljs-number">2</span>.sign校验失败，给出错误信息，调用登出接口<br></code></pre>

<hr>



<h5 id="用户退出接口">用户退出接口</h5>

<ul><li>提供方：<code>4399平台</code></li>
<li>使用场景：游戏sign校验失败，用户登出，切换账号，断线重连时，调用此接口</li>
<li>接口： <code>无</code></li>
<li>测试接口：<code>无</code></li>
<li>调用方式:js调用</li>
</ul>



<pre class="prettyprint hljs-dark"><code class="hljs less"> 输入：<span class="hljs-tag">js</span>代码<br>    <span class="hljs-tag">parent</span><span class="hljs-class">.postMessage</span>({<br>      <span class="hljs-attribute">eventType</span>: <span class="hljs-string">'logout'</span><br>    }, <span class="hljs-string">'*'</span>);<br></code></pre>



<pre class="prettyprint hljs-dark"><code class="hljs cpp"> 输出:<br>     <span class="hljs-number">1.</span>跳转到登录界面<br></code></pre>

<hr>



<h4 id="支付流程">支付流程</h4>



<h5 id="支付时序图">支付时序图</h5>



<div class="sequence-diagram" rel="0fc9639b6da4aebdca3643b015cb18b8"><span><img type="image/png" width="490.5" height="319" longdesc="__SVG__undefined" src="" style="margin-top:0;margin-bottom:0;"></span></div>

<ul><li>用户点击充值按钮，弹开充值面板；</li>
<li>平台根据用户选择的充值渠道下单 <br>
<ul>
<li>下单成功后，通知游戏发放游戏币，并展示结果给用户</li>
<li>下单失败，展示结果给用户</li></ul></li>
</ul>



<h5 id="支付面板接口">支付面板接口</h5>

<ul><li>提供方：<code>4399平台</code></li>
<li>使用场景：玩家点击充值，打开充值面板</li>
<li>接口： <code>无</code></li>
<li>测试接口：<code>无</code></li>
<li>调用方式:js调用</li>
</ul>



<pre class="prettyprint hljs-dark"><code class="hljs lasso"> 输入：<br>    <span class="hljs-keyword">parent</span><span class="hljs-built_in">.</span>postMessage({<br>      eventType: <span class="hljs-string">'openPay'</span>,<br>      <span class="hljs-built_in">data</span>: {<br>        <span class="hljs-comment">// 充值金额（人民币：元） 只能为整数</span><br>        money: <span class="hljs-number">10</span>,<br>        <span class="hljs-comment">// 游戏的充值订单编号 最多32位</span><br>        mark: <span class="hljs-string">'12345678901234567890123456789012'</span>,<br>        <span class="hljs-comment">// 服务器编号 不能为空或者0</span><br>        server: <span class="hljs-number">1</span>,<br>        <span class="hljs-comment">// 透传参数，用于充值成功后的服务端回调地址</span><br>        extra: <span class="hljs-string">'测试数据透传'</span><br>      }<br>    }, <span class="hljs-string">'*'</span>);<br></code></pre>

<pre class="prettyprint hljs-dark"><code class="hljs"> 输出:<br>    打开充值面板<br></code></pre>

<hr>



<h5 id="发放游戏币接口">发放游戏币接口</h5>

<ul><li>提供方：<code>游戏方</code></li>
<li>使用场景：充值成功后，平台将通过服务端异步通知游戏方发放相应的游戏币给玩家；</li>
<li>接口： <code>游戏方</code></li>
<li>测试接口：<code>游戏方</code></li>
<li>调用方式:POST</li>
</ul>



<pre class="prettyprint hljs-dark"><code class="hljs cpp">注意：<br>    - 该接口，做一下ip白名单，非<span class="hljs-number">4399</span>的ip不允许访问；<span class="hljs-number">4399</span>的ip段：<span class="hljs-number">115.182</span><span class="hljs-number">.52</span>.*<br>    - 平台这边的超时时间设置<span class="hljs-number">10</span>s，尽量在<span class="hljs-number">10</span>s内返回结果<br>    - userName必须rawurldecode，以免中文账号或账号含有特殊字符如@/+_等，会发货不成功或sign验证不成功<br></code></pre>



<pre class="prettyprint hljs-dark"><code class="hljs xquery">输入:<br>       orderId =&gt; <span class="hljs-string">'2015111119341757100101'</span>,  /// <span class="hljs-number">4399</span>订单号<br>       gameId =&gt; <span class="hljs-number">100039809</span>,                  /// 该游戏在原创平台的ID<br>       userId =&gt; <span class="hljs-number">594437088</span>,                  /// 用户ID<br>       userName =&gt; <span class="hljs-string">'huangmkhmk'</span>,             /// 用户名<br>       money =&gt; <span class="hljs-number">10</span>,                          /// 支付金额，人民币<br>       gameMoney =&gt; <span class="hljs-number">100</span>,                     /// 发放的游戏币<br>       mark=&gt; <span class="hljs-string">'2015111119341757100101'</span>,      /// 游戏订单ID<br>       server =&gt; <span class="hljs-string">'1'</span>,                        /// 游戏服务器<br>       time =&gt; <span class="hljs-number">1447228562</span>,                   /// 时间戳，精确到秒<br>       ext =&gt; <span class="hljs-string">'透传参数'</span>,                     /// 由支付界面跳转接口传递的透传参数，原样返回给游戏服务器<br>       sign =&gt; <span class="hljs-string">'9397176eabd8c494946df910d98a41f2'</span>, /// sign签名，算法：md5(sprintf(<span class="hljs-string">"gameId=%smark=%smoney=%sorderId=%sserver=%stime=%suserId=%suserName=%s%s"</span>, <span class="hljs-variable">$gameId</span>, <span class="hljs-variable">$mark</span>, <span class="hljs-variable">$money</span>, <span class="hljs-variable">$orderId</span>, <span class="hljs-variable">$server</span>, <span class="hljs-variable">$time</span>, <span class="hljs-variable">$userId</span>, <span class="hljs-variable">$userName</span>, <span class="hljs-variable">$callbackKey</span>));<br>       test =&gt; <span class="hljs-number">1</span>,                            /// 测试模式test=<span class="hljs-number">1</span>，正式模式test参数不存在或为<span class="hljs-number">0</span><br></code></pre>



<pre class="prettyprint hljs-dark"><code class="hljs cpp">输出:<br>    以下返回值为<span class="hljs-keyword">int</span>型<br>        <span class="hljs-number">1</span> =&gt; 成功，如果订单重复也直接返回<span class="hljs-number">1</span><br>        -<span class="hljs-number">1</span> =&gt; 失败，提交参数不全<br>        -<span class="hljs-number">2</span> =&gt; 验证错误<br>        -<span class="hljs-number">3</span> =&gt; 用户不存在<br>        -<span class="hljs-number">4</span> =&gt; 请求超时（为保证用户体验超过<span class="hljs-number">10</span>秒请输出此代码）<br>        -<span class="hljs-number">5</span> =&gt; 充值比例异常（游戏币除以人民币 不等于兑换比率）<br>        -<span class="hljs-number">6</span> =&gt; 请求ip验证失败。（请限制充值请求的来源ip为：<span class="hljs-number">115.182</span><span class="hljs-number">.52</span>.* ip段 及 <span class="hljs-number">113.107</span><span class="hljs-number">.149</span><span class="hljs-number">.212</span>）<br>        -<span class="hljs-number">7</span> =&gt; 要充值的服务器不存在(server参数不正确)<br>        -<span class="hljs-number">8</span> =&gt; 充值金额异常（PC端可改金额，可能导致下单金额和支付金额不一致）<br>        -<span class="hljs-number">99</span> =&gt; 其他原因导致的充值失败<br></code></pre>



<h4 id="常见问题说明">常见问题说明</h4>

<ul><li>加密规则说明： <br>
sign算法中的参数都是以rawurldecode后的参数（参数原始值）进行加密；所以游戏登录接口和支付回调接口（发货接口）接收参数时，需对每个参数解密rawurldecode一遍，再进行sign校验</li>
</ul>



<pre class="prettyprint hljs-dark"><code class="hljs groovy">附录：<br>    + php的rawurlencode和js的encodeURIComponent遵循的是国际标准备忘录RFC <span class="hljs-number">3986</span>，理论上可互通<br>    + php的rawurlencode和urlencode区别是在空格加密不一样，<span class="hljs-string">rawurlencode:</span>%<span class="hljs-number">20</span> <span class="hljs-string">urlencode:</span>+<br>    + [js的base64库](<span class="hljs-string">https:</span><span class="hljs-comment">//github.com/dankogai/js-base64/blob/master/base64.js)</span><br></code></pre>

<ul><li>调用支付页面，确认支付需重新登录，登录后出现以下页面 <br>
<ul>
<li>主要问题是：chrome浏览器模拟移动端，先用pc端账号登录，然后又切成移动端；这个时候有可能会出现accessToken出错</li>
<li>解决：可退出账号后，重新以移动端登录，即可解决</li></ul></li>
</ul>



<p><img longdesc="./1490694348919.png" alt="Alt text" title="" type="image/png" src="" class=""></p>

<ul><li>短连接游戏充值完毕的通知问题 <br>
短连接游戏在充值完，游戏客户端接收不到充值通知；可在点击充值按钮时，弹出类似以下的对话框；并调用平台支付页面接口；玩家点击确定后，重新获取游戏币接口，展现在游戏中（尽量不做整个页面刷新的交互体验会比较好）</li>
</ul>



<p><img longdesc="./1490693929352.png" alt="Alt text" title="" type="image/png" src="" class=""></p></div></body></html>wPw16T/3RvTVXgsBn4N7UZpf2zB3cdDGOhwfQgl3Yvzw8D/D+rGgNLAMEDUAAAAAElFTkSuQmCC" class=""></p></div></body></html>